package basic_grammar

import (
	"fmt"
	"math"
)

func TestOperator() {
	OperatorTest()
}

//运算符
// 算数运算符 + - * / % ++ --
// 赋值运算符 += -= *= /= %=
// 比较(关系)运算符 == != < <= > >=
// 逻辑运算符 && || !
// 位运算符 & | ^ &^ << >>
// 其他运算符 & *

//a % b = a - a / b * b
func ModTest() {
	fmt.Println("10%3=", 10%3)
	fmt.Println("-10%3=", -10%3)
	fmt.Println("10%-3=", 10%-3)
	fmt.Println("-10%-3=", -10%-3)
}

func OperatorTest() {
	// 模拟整型的加减过程
	a := culIntegerComplement(128)
	b := culIntegerComplement(-8)
	fmt.Println(a)
	fmt.Println(b)
	fmt.Println(arrayPlus(a, b))

	// 位运算
	//a := culIntegerComplement(-2)
	//b := culIntegerComplement(1)
	//fmt.Println(-2 &^ 1)
	//res := simulateANDOR(a, b)
	//fmt.Println(res)
	//fmt.Println(transInteger(res))
	//
	//c := culIntegerComplement(3)
	//res = simulateLEFTMOVE(c, 2)
	//fmt.Println(res)
	//fmt.Println(transInteger(res))

}

/*
模拟位运算
*/

// 按位与&
//运算规则: 0&0=0;  0&1=0;   1&0=0;    1&1=1;
func simulateAND(a [64]int, b [64]int) [64]int {
	var res [64]int
	for i := 0; i < 64; i++ {
		if a[i] == 1 && b[i] == 1 {
			res[i] = 1
		} else {
			res[i] = 0
		}
	}
	return res
}

//按位或|
//运算规则 : 0|0=0;  0|1=1;  1|0=1;   1|1=1

//按位异或(XOR) ^
//运算规则 : 0^0=0;  0^1=1;  1^0=1;   1^1=0;

//按位清空(AND NOT) &^
//运算规则：0&^0=0;  1&^0=1;  0&^1=0; 1&^1=0;
//运算符是双目运算符
//功能同a&(^b)相同

func simulateANDOR(a [64]int, b [64]int) [64]int {
	var res [64]int
	for i := 0; i < 64; i++ {
		if b[i] == 1 {
			res[i] = 0
		} else if b[i] == 0 {
			res[i] = a[i]
		}
	}
	return res
}

//<< 左移,计算上相当于乘以2^n
func simulateLEFTMOVE(input [64]int, moveStamp int) [64]int {
	for i := 0; i < 64-moveStamp; i++ {
		input[i] = input[i+moveStamp]
	}
	for j := 64 - moveStamp; j < 64; j++ {
		input[j] = 0
	}
	return input
}

//>> 右移,计算上相当于除以2^n

/*
计算整数的补码
有符号最高为代表符号，0+，1-
正数的原码/补码/反码均相同，为2进制
负数反码 = 原码符号不变，其余位置取反
负数补码 = 反码+1
补码运算
*/
func culIntegerComplement(i int) [64]int {
	if i >= 0 {
		return culPositiveInteger(i)
	} else {
		return culNegativeInteger(i)
	}
}

func culNegativeInteger(i int) [64]int {
	var res [64]int
	res[0] = 1
	iabs := int(math.Abs(float64(i)))

	for m := 63; m > 0; m-- {
		if iabs%2 == 0 {
			res[m] = 1
		} else {
			res[m] = 0
		}
		iabs /= 2
	}

	return plusOne(res, 63)

}

func plusOne(res [64]int, index int) [64]int {
	singleRes := res[index] + 1
	if singleRes == 2 {
		res[index] = 0
		res = plusOne(res, index-1)
	} else {
		res[index] = singleRes
	}
	return res
}

func culPositiveInteger(i int) [64]int {
	var res [64]int
	var lsb int
	for m := 63; m >= 0; m-- {
		lsb = i % 2
		i /= 2
		res[m] = lsb
	}
	return res
}

func arrayPlus(a [64]int, b [64]int) int {
	var res [64]int
	m := 0
	for i := 63; i >= 0; i-- {
		singleRes := a[i] + b[i] + m
		if singleRes < 2 {
			res[i] = singleRes
			m = 0
		} else if singleRes == 2 {
			res[i] = 0
			m = 1
		} else if singleRes == 3 {
			res[i] = 1
			m = 1
		}
	}
	return transInteger(res)
}

func transInteger(res [64]int) int {
	var finalRes int
	if res[0] == 0 {
		finalRes = transPositiveInteger(res)
	} else if res[0] == 1 {
		finalRes = transNegativeInteger(res)
	}
	return finalRes
}

func transPositiveInteger(res [64]int) int {
	finalRes := 0
	for i := 1; i < 64; i++ {
		finalRes += res[i] * int(math.Pow(float64(2), float64(63-i)))
	}
	return finalRes
}

func transNegativeInteger(res [64]int) int {
	minusOneRes := minusOne(res, 63)
	return -1 * transPositiveInteger(originCode(minusOneRes))
}

func minusOne(res [64]int, index int) [64]int {
	singleRes := res[index] - 1
	if singleRes >= 0 {
		res[index] = singleRes
	} else if singleRes == -1 {
		res[index] = 1
		res = minusOne(res, index-1)
	}
	return res
}

func originCode(res [64]int) [64]int {
	for i := 1; i < 64; i++ {
		if res[i] == 1 {
			res[i] = 0
		} else if res[i] == 0 {
			res[i] = 1
		}
	}
	return res
}
